/**************************************************************************
** Qt Creator license header template
**   Special keywords: Programmer 2012/4/19 2012
**   Environment variables: 
**   To protect a percent sign, use '%'.
**************************************************************************/

#include "midpointprogressivemesh.h"

void ProgressiveMeshMid(MyTriMesh& m, int targetFaceNum, vcg::BaseParameterClass &pp, GLArea *gl)
{
    vcg::LocalOptimization<MyTriMesh> DeciSession(m,&pp);
    DeciSession.Init<MidpointProgressiveMesh>();
    DeciSession.SetTargetSimplices(targetFaceNum);
    DeciSession.SetTimeBudget(0.1f);
    while( DeciSession.DoOptimization() && m.fn > targetFaceNum )
    {
        gl->updateGL();
    }
    //DeciSession.Finalize<MidpointProgressiveMesh>();
    vcg::tri::UpdateNormals<MyTriMesh>::PerVertexNormalizedPerFace(m);
    vcg::tri::UpdateBounding<MyTriMesh>::Box(m);
}

//find the faces from vl to vr in CCW.
void FindEdgeSet(std::vector<vcg::face::VFIterator<MyFace> >& es,VSplitMid* s)
{
    MyVertex* nextv = s->vl;
    vcg::face::VFIterator<MyFace> vfi(s->v);

    //clear Visited flag
    for(; !vfi.End(); ++vfi)
        vfi.f->ClearV();

    while(true){
        vfi.f = s->v->VFp();
        vfi.z = s->v->VFi();
        for(; !vfi.End();++vfi){
            if(!vfi.f->IsV() && vfi.f->V((vfi.z+1)%3)==nextv){
                es.push_back(vfi);
                vfi.f->SetV();
                nextv = vfi.f->V((vfi.z+2)%3);
                break;
            }
        }
        if(s->vr==nextv){
            break;
        }

    }
}


void RestoreProgressiveMeshMid(MyTriMesh& m,MidParameters& pp,GLArea* gl)
{
    std::vector<vcg::face::VFIterator<MyFace> > es;

    VSplitMid* s = NULL;
    MyTriMesh::VertexPointer vNew = NULL;//,vl,vr;

    MyFace* f1 = NULL;
    MyFace* f2 = NULL;
    int i = 10;
    while(!pp.vSplits.empty()){

        s = pp.getRemoveSplit();
        assert(!s->v->IsD() && !s->vl->IsD() && !s->vr->IsD());

        //add a new Vertex
        vNew = pp.getRemoveVertex();
        assert(vNew->IsD());
        vNew->ClearD();
        vNew->P() = s->v0;
        vNew->VFi() = -1;
        vNew->VFp() = NULL;
        m.vn++;



//        QMessageBox msg;
//        msg.setText(QString("size left:"+pp.vSplits.size()));
//        msg.setWindowTitle(QString("info"));
//        msg.exec();
        es.clear();
        FindEdgeSet(es,s);
        assert(!es.empty());

        //setting the VF topo for vNew
        for(std::vector<vcg::face::VFIterator<MyFace> >::iterator i=es.begin(); i!=es.end();i++){

            vcg::face::VFDetach(*((*i).f),(*i).z);
            (*i).f->V((*i).z) = vNew;
            vcg::face::VFAppend((*i).f,(*i).z);
        }

        //add two new faces.
        f1 = pp.getRemoveFace();
        f2 = pp.getRemoveFace();
        assert(f1->IsD() && f2->IsD());
        f1->ClearD();
        f2->ClearD();
        m.fn += 2;

        f1->V(0) = vNew;
        f1->V(1) = s->v;
        f1->V(2) = s->vl;
        vcg::face::VFAppend<MyFace>(f1,0);
        vcg::face::VFAppend<MyFace>(f1,1);
        vcg::face::VFAppend<MyFace>(f1,2);
        f2->V(0) = vNew;
        f2->V(1) = s->vr;
        f2->V(2) = s->v;
        vcg::face::VFAppend<MyFace>(f2,0);
        vcg::face::VFAppend<MyFace>(f2,1);
        vcg::face::VFAppend<MyFace>(f2,2);

        s->v->P() = s->v1;

        //vcg::tri::UpdateTopology<MyTriMesh>::FaceFace(m);
      // gl->updateGL();

        /////////////////////////////
    }
}
